// Copyright (c) 2021 G_night

/*
连接池相关行为：
	. 接收任务
	. 检查缓存队列是否有待执行的任务
*/
package agopool

import (
	"time"
)

// 接收任务
func (p *AgoPool) Put(behavior func(v ...interface{}), param []interface{}) (ok bool, err error) {

	p.Lock()
	defer p.Unlock()

	task := &Task{
		Behavior: behavior,
		Params:   param,
	}

	if p.status == CLOSED { // 如果任务池处于关闭状态, 再 put 任务会返回 ErrPoolAlreadyClosed 错误
		return false, PoolClosedError
	}

	// 启动worker
	if p.GetWorker() < p.GetCap() {
		p.run()
	} else if !p.isBlock {
		p.overTimeFunc.Handler(p.overTimeFunc.Params)
		return false, TimeoutError
	}

	// 将任务推入队列, 等待消费
	p.chTask <- task

	// 返回正确状态
	return true, nil
}

// 启动worker
func (p *AgoPool) run() {
	// 增加
	p.incWorker()

	// 执行具体操作
	go func() {
		defer func() {
			p.decWorker()
			if r := recover(); r != nil {
				if p.panicHandler != nil {
					p.panicHandler(r)
				} else {
					defaultDisposeError(r)
				}
			}
			p.checkWorker() // worker 退出时检测是否有可运行的 worker
		}()
		for {
			select {
			case task, ok := <-p.chTask:
				if !ok {
					return
				}
				task.Behavior(task.Params...)
			}
		}
	}()
}

// 关闭线程池
func (p *AgoPool) Close() {
	p.setStatus(CLOSED) // 设置 status 为已停止

	// 阻塞等待所有任务被 worker 消费
	for len(p.chTask) > 0 {
		time.Sleep(2 * time.Second)
	}

	close(p.chTask) // 关闭任务队列
}

// 检查尚未完成的
func (p *AgoPool) checkWorker() {
	if p.runningWorkers == 0 && len(p.chTask) > 0 {
		p.run()
	}
}
